/* eslint no-extend-native: ["error", { "exceptions": ["Date"] }] */
type FormatType = 'y' | 'm' | 'd' | 'h' | 'i' | 's' | 'a';
type SetFun = 'setFullYear' | 'setMonth' | 'setDate' | 'setHours' | 'setMinutes' | 'setSeconds' | 'setMilliseconds';
type GetFun =
  | 'getFullYear'
  | 'getMonth'
  | 'getDate'
  | 'getHours'
  | 'getMinutes'
  | 'getSeconds'
  | 'getMilliseconds'
  | 'getDay';
(() => {
  const special = {
    y: {
      // 年
      get: 'getFullYear',
      set: 'setFullYear',
    },
    m: {
      // 月
      get: 'getMonth',
      set: 'setMonth',
    },
    d: {
      // 日
      get: 'getDate',
      set: 'setDate',
    },
    h: {
      // 时
      get: 'getHours',
      set: 'setHours',
    },
    i: {
      // 分
      get: 'getMinutes',
      set: 'setMinutes',
    },
    s: {
      // 秒
      get: 'getSeconds',
      set: 'setSeconds',
    },
    ms: {
      // 毫秒
      get: 'getMilliseconds',
      set: 'setMilliseconds',
    },
    a: {
      // 周
      set: null,
      get: 'getDay',
    },
  };
  /**
   * 接收一系列的时间日期字符串并替换成相应的值,如：{y}-{m}-{d} {h}:{i}:{s}
   * new Date().format()
   **/
  if (!Date.prototype.format) {
    Date.prototype.format = function(pattern?: string): string {
      const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}';
      const formatObj = {
        y: this.getFullYear(),
        m: this.getMonth() + 1,
        d: this.getDate(),
        h: this.getHours(),
        i: this.getMinutes(),
        s: this.getSeconds(),
        a: this.getDay(),
      };

      const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
        const _key = key as FormatType;
        let value: string | number = formatObj[_key];
        // Note: getDay() returns 0 on Sunday
        if (key === 'a') {
          return ['日', '一', '二', '三', '四', '五', '六'][value];
        }
        if (result.length > 0 && value < 10) {
          value = '0' + value;
        }
        return String(value || 0);
      });
      return time_str;
    };
  }

  /**
   * 返回包含时间数值的对象
   * new Date().ToObject()
   **/
  if (!Date.prototype.ToObject) {
    Date.prototype.ToObject = function() {
      return {
        y: this.getFullYear(),
        m: this.getMonth() + 1,
        d: this.getDate(),
        h: this.getHours(),
        i: this.getMinutes(),
        s: this.getSeconds(),
        ms: this.getMilliseconds(),
        a: this.getDay(),
      };
    };
  }

  /**
   * 克隆
   * new Date().clone()
   **/
  if (!Date.prototype.clone) {
    Date.prototype.clone = function() {
      return new Date(this.valueOf());
    };
  }
  /**
   * 设置时间，并返回设置后的时间
   * new Date().set('d',7)
   **/
  if (!Date.prototype.set) {
    Date.prototype.set = function(unit: UnitType, value: number) {
      const d: Date = this.clone();
      const fun = special[unit].set;
      if (fun) {
        d[fun as SetFun](value);
      }

      return d;
    };
  }

  /**
   * 获取时间
   * new Date().get('d')
   **/
  if (!Date.prototype.get) {
    Date.prototype.get = function(unit: UnitType) {
      const d: Date = this.clone();
      return d[special[unit].get as GetFun]();
    };
  }
  /**
   * 获取指定时间增加后的时间
   * new Date().add(7, 'm')
   **/
  if (!Date.prototype.add) {
    Date.prototype.add = function(value: number, unit?: UnitType) {
      let _unit = unit;
      _unit = _unit ? _unit : 'd';
      const units: number = this.get(_unit);
      const d = this.set(_unit, units + value);
      return d;
    };
  }
  /**
   * 获取指定时间减少后的时间
   * new Date().subtract(7, 'd')
   **/
  if (!Date.prototype.subtract) {
    Date.prototype.subtract = function(value: number, unit?: UnitType) {
      let _unit = unit;
      _unit = _unit ? _unit : 'd';
      const units: number = this.get(_unit);
      const d = this.set(_unit, units - value);
      return d;
    };
  }
  /**
   * 时间差
   * new Date().diff(newday, 'd',true)
   **/
  if (!Date.prototype.diff) {
    Date.prototype.diff = function(date: ConfigType, unit?: UnitType, float?: boolean) {
      let _unit = unit;
      let _date = date;
      const dif1: number = this.valueOf();
      _unit = _unit ? _unit : 'ms';
      if (typeof _date === 'string') {
        _date = new Date(_date);
      } else if (typeof _date === 'number') {
        _date = _date.parseTime();
        _date = new Date(_date);
      }
      const dif2: number = _date.valueOf();
      let difms: number = Math.abs(dif2 - dif1); // 毫秒
      let b = 1;
      switch (_unit) {
        case 's':
          b = 1000; // 秒
          break;
        case 'i':
          b = 1000 * 60; // 分
          break;
        case 'h':
          b = 1000 * 60 * 60; // 时
          break;
        case 'd':
          b = 1000 * 60 * 60 * 24; // 日
          break;
        case 'a':
          b = 1000 * 60 * 60 * 24 * 7; // 周
          break;
        case 'm':
          b = 1000 * 60 * 60 * 24 * 30; // 月
          break;
        case 'y':
          b = 1000 * 60 * 60 * 24 * 365; // 年
          break;
        default:
          b = 1;
      }
      difms = difms / b;
      if (float) {
        difms = Math.round(Number(difms.toFixed()));
      }
      return difms;
    };
  }
  /**
   * 是否之前
   * 检查一个 date 对象是否在另一个 date 对象时间之前。
   * new Date().isBefore(newday, 'year'); // false
   **/
  if (!Date.prototype.isBefore) {
    Date.prototype.isBefore = function(date: ConfigType, unit?: UnitType) {
      let _date = date;
      let _this: number;
      let _that: number;
      if (typeof _date === 'string') {
        _date = new Date(_date);
      } else if (typeof _date === 'number') {
        _date = _date.parseTime();
        _date = new Date(_date);
      }
      if (unit) {
        _this = this.get(unit);
        _that = _date.get(unit);
      } else {
        _this = this.valueOf();
        _that = _date.valueOf();
      }
      let re = false;
      if (_this > _that) {
        re = true;
      }
      return re;
    };
  }

  /**
   * 是否之后
   * 检查一个 Date 对象是否在另一个 Date 对象时间之后。
   * new Date().isAfter(newday, 'y'); // false
   **/
  if (!Date.prototype.isAfter) {
    Date.prototype.isAfter = function(date: ConfigType, unit?: UnitType) {
      let _date = date;
      let _this: number;
      let _that: number;
      if (typeof _date === 'string') {
        _date = new Date(_date);
      } else if (typeof _date === 'number') {
        _date = _date.parseTime();
        _date = new Date(_date);
      }
      if (unit) {
        _this = this.get(unit);
        _that = _date.get(unit);
      } else {
        _this = this.valueOf();
        _that = _date.valueOf();
      }
      let re = false;
      if (_this < _that) {
        re = true;
      }
      return re;
    };
  }
  /**
   * 来展示一个时间是否介于两个时间之间.
   * new Date().IsBetween(day1,day2, 'y'); // false
   **/
  if (!Date.prototype.IsBetween) {
    Date.prototype.IsBetween = function(date1: ConfigType, date2: ConfigType, unit?: UnitType) {
      let _date1 = date1;
      let _date2 = date2;
      let _this: number;
      let _that1: number;
      let _that2: number;
      if (typeof _date1 === 'string') {
        _date1 = new Date(_date1);
      } else if (typeof _date1 === 'number') {
        _date1 = _date1.parseTime();
        _date1 = new Date(_date1);
      }
      if (typeof _date2 === 'string') {
        _date2 = new Date(_date2);
      } else if (typeof _date2 === 'number') {
        _date2 = _date2.parseTime();
        _date2 = new Date(_date2);
      }
      if (unit) {
        _this = this.get(unit);
        _that1 = _date1.get(unit);
        _that2 = _date2.get(unit);
      } else {
        _this = this.valueOf();
        _that1 = _date1.valueOf();
        _that2 = _date2.valueOf();
      }
      let re = false;
      if (_that1 < _this && _this < _that2) {
        re = true;
      }
      return re;
    };
  }
  /**
   * 是否相同
   * 检查一个 Date 对象是否和另一个 Date 对象时间相同。
   * new Date().isSame(newday, 'y'); // false
   **/
  if (!Date.prototype.isSame) {
    Date.prototype.isSame = function(date: ConfigType, unit?: UnitType) {
      let _date = date;
      let _this: number;
      let _that: number;
      if (typeof _date === 'string') {
        _date = new Date(_date);
      } else if (typeof _date === 'number') {
        _date = _date.parseTime();
        _date = new Date(_date);
      }
      if (unit) {
        _this = this.get(unit);
        _that = _date.get(unit);
      } else {
        _this = this.valueOf();
        _that = _date.valueOf();
      }
      let re = false;
      if (_this === _that) {
        re = true;
      }
      return re;
    };
  }
  /**
   * 天数 (月):返回月份的天数。
   * new Date().daysInMonth()
   **/
  if (!Date.prototype.daysInMonth) {
    Date.prototype.daysInMonth = function() {
      const year = this.getFullYear();
      const month = this.getMonth() + 1;
      const d = new Date(year, month, 0);
      return d.getDate();
    };
  }
})();

export {};
